#include "../liolib/lioflat.h"									

namespace Lio {

#define FILTERS 3

int			M=32,N=16;
CSTR		bmpFileName=_T("data/base.bmp");
BOOL
	lp=FALSE,light=TRUE,
	sp=FALSE,fill=TRUE,
	gp=FALSE,txt=TRUE,
	fp=FALSE;
double
	xrot=0, // X Rotation
	yrot=0, // Y Rotation
	zrot=0,
	xspeed=0.0f, // X Rotation Speed
	yspeed=10.0f, // Y Rotation Speed
	zspeed=0.0f; // Y Rotation Speed
GLfloat
	sum=0,
	a=1,b=1,c=1,
	z=-5.0f, // Depth Into The Screen
	LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }, // Ambient Light Values
	LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }, // Diffuse Light Values
	LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f }, // Light Position
	fogColor[4]= {0.0f, 0.0f, 0.0f, 1.0f}; // Fog Color
GLuint
	filter=2, // Which Filter To Use
	fogMode[]= { GL_EXP, GL_EXP2, GL_LINEAR }, // Storage For Three Types Of Fog
	minFilterMode[]={ GL_NEAREST,	GL_LINEAR,	GL_LINEAR_MIPMAP_NEAREST},
	magFilterMode[]={ GL_NEAREST,	GL_LINEAR,	GL_LINEAR},
	mipmapped[]=	{ FALSE,		FALSE,		TRUE},
	fogFilter= 0; // Which Fog To Use 
Texture textures[FILTERS];
DisplayList list;

double _a=0,_b=0,_c=0;
int _N=0,_M=0;

class Ellipsoid:public FlatApplication
{
	Image image;
	BOOL create();
	void update();
	BOOL glCreate();
	void draw2D();
	void draw3D();

	void rebuild();
} ellipsoid;

BOOL Ellipsoid::create ()	
{
	FlatApplication::create();
	name=_T("Ellipsoid");

	display.width=1024;
	display.height=768;
	
	//allowYield=FALSE;

	txt=readBitmap(bmpFileName,&image);

	return TRUE;
}

BOOL Ellipsoid::glCreate ()	
{
	FlatApplication::glCreate();

	if(txt)
	{
		Texture * t;
		for(int j=0;j<FILTERS;j++)
		{
			t = textures+j;
			t->minFilter=magFilterMode[j];
			t->magFilter=magFilterMode[j];
			t->mipmapped=mipmapped[j];
			t->create(&image);
		}
		glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
	}

	glShadeModel(GL_SMOOTH); // Enables Smooth Shading
	glClearColor(
		fogColor[RED],
		fogColor[GREEN],
		fogColor[BLUE],
		fogColor[ALPHA]);
	setDepthTest(TRUE,1,GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations

	createLight(GL_LIGHT1,LightAmbient,LightDiffuse,LightPosition);			// Position The Light
	setLight(light);

	createFog(1.0f,5.0f,fogColor,0.35f);
	if(!fogFilter)
	{
		glDisable(GL_FOG); // Enables GL_FOG
	}
	else
	{
		glEnable(GL_FOG); // Enables GL_FOG
		glFogi (GL_FOG_MODE, fogMode[fogFilter-1]); // Fog Mode
	}
	fillPolygon(fill);
	list.create(window.hDC);
	rebuild();
	return TRUE;
}

void Ellipsoid::draw3D()
{
	glTranslatef(0,0,z);
	glRotate(xrot,yrot,zrot);
	textures[filter].bind();

	if(_a!=a||_b!=b||_c!=c||_N!=N||_M!=M)
		rebuild();
	list.execute();
}

void Ellipsoid::rebuild()
{
	_a=a;_b=b;_c=c;_N=N;_M=M;
	CompileDisplayList compile(&list);
	drawEllipsoid(a,b,c,N,M);
	//drawParallel();
}

void Ellipsoid::draw2D()
{
	font.color=INT_YELLOW;
	font.x=20;
	font.y=20;
	glPrint(&font,_T("speedX:"));
	font.y+=18;
	glPrint(&font,_T("speedY:"));
	font.y+=18;
	glPrint(&font,_T("speedZ:"));
	font.color=INT_WHITE;
	font.x+=70;
	font.y=20;
	glPrint(&font,_T("% .2f"),xspeed);
	font.y+=18;
	glPrint(&font,_T("% .2f"),yspeed);
	font.y+=18;
	glPrint(&font,_T("% .2f"),zspeed);

	font.color=INT_YELLOW;
	font.x+=70;
	font.y=20;
	glPrint(&font,_T("angleX:"));
	font.y+=18;
	glPrint(&font,_T("angleY:"));
	font.y+=18;
	glPrint(&font,_T("angleZ:"));
	font.color=INT_WHITE;
	font.x+=70;
	font.y=20;
	glPrint(&font,_T("%+04d deg"),int(xrot)%360);
	font.y+=18;
	glPrint(&font,_T("%+04d deg"),int(yrot)%360);
	font.y+=18;
	glPrint(&font,_T("%+04d deg"),int(zrot)%360);

	font.color=INT_YELLOW;
	font.x+=100;
	font.y=20;
	glPrint(&font,_T("m:"));
	font.y+=18;
	glPrint(&font,_T("n:"));
	font.color=INT_WHITE;
	font.x+=10;
	font.y=20;
	glPrint(&font,_T("%6d"),M);
	font.y+=18;
	glPrint(&font,_T("%6d"),N);
	font.y+=18;
	glPrint(&font,_T("%6d"),N*M);

	font.color=INT_YELLOW;
	font.x+=90;
	font.y=20;
	glPrint(&font,_T("filter:"));
	font.y+=18;
	glPrint(&font,_T("fog:"));
	font.y+=18;
	glPrint(&font,_T("light:"));
	font.color=INT_WHITE;
	font.x+=70;
	font.y=20;
	glPrint(&font,_T("%d"),filter);
	font.y+=18;
	glPrint(&font,_T("%d"),fogFilter);
	font.y+=18;
	glPrint(&font,_T("%d"),light);

	font.color=INT_YELLOW;
	font.x+=40;
	font.y=20;
	glPrint(&font,_T("a:"));
	font.y+=18;
	glPrint(&font,_T("b:"));
	font.y+=18;
	glPrint(&font,_T("c:"));
	font.color=INT_WHITE;
	font.x+= 30;
	font.y=20;
	glPrint(&font,_T("%3.2f"),a);
	font.y+=18;
	glPrint(&font,_T("%3.2f"),b);
	font.y+=18;
	glPrint(&font,_T("%3.2f"),c);

	font.color=INT_YELLOW;
	font.x+=60;
	font.y=20;
	glPrint(&font,_T("loop:"));
	font.y+=18;
	glPrint(&font,_T("rate:"));
	font.color=INT_WHITE;
	font.x+= 60;
	font.y=20;
	glPrint(&font,_T("%.1f ms"),1e3*loopTime);
	font.y+=18;
	glPrint(&font,_T("%.1f"),INV(loopTime));
}

void Ellipsoid::update()
{
	if (keyboard.keys[VK_ESCAPE])					// Is ESC Being Pressed?
	{
		terminate();
	}
	if (keyboard.keys[VK_F1])						// Is F1 Being Pressed?
	{
		toggleFullscreen();
		keyboard.keys[VK_F1] = FALSE;
	}
	if (keyboard.keys['L'])					// Is L Being Typed?
	{
		if(!lp)
		{
			lp=TRUE; // lp Becomes TRUE
			light=!light; // Toggle Light TRUE/FALSE
			setLight(light);
		}
	}
	else
	{
		lp = FALSE;
	}
	if (keyboard.keys['G'])
	{
		if(!gp) // Is The GREEN Key Being Pressed?
		{
			gp=TRUE; // gp Is Set To TRUE
			if (fogFilter<3)
			{
				fogFilter++; // Increase fogFilter By One	
			}
			else
			{
				fogFilter=0; // If So, Set fogFilter To Zero
			}
			if(!fogFilter)
			{
				glDisable(GL_FOG); // Enables GL_FOG
			}
			else
			{
				glEnable(GL_FOG); // Enables GL_FOG
				glFogi (GL_FOG_MODE, fogMode[fogFilter-1]); // Fog Mode
			}
		}
	}
	else
	{
		gp=FALSE; // If So, gp Is Set To FALSE
	}
	if (keyboard.keys['F'])					// Is F Being Typed?
	{
		if(!fp)
		{
			fp=TRUE; // fp Becomes TRUE
			if(filter<FILTERS-1)
				filter++; // filter Value Increases By One
			else
				filter=0; // Set filter To 0
		}
	}
	else
	{
		fp=FALSE;
	}
	if (keyboard.keys[VK_SPACE])					// Is Space Being Typed?
	{
		if(!sp)
		{
			sp=TRUE; // fp Becomes TRUE
			fill=!fill;
			fillPolygon(fill);
			//glDisable(GL_TEXTURE_2D);
		}
	}
	else
	{
		sp=FALSE;
	}
	if (keyboard.keys[VK_PRIOR]) // Is Page Up Being Pressed?
	{
		z-=0.02f; // If So, Move Into The Screen
	}
	if (keyboard.keys[VK_NEXT]) // Is Page Down Being Pressed?
	{
		z+=0.02f; // If So, Move Towards The Viewer
	}
	if (keyboard.keys[VK_UP]) // Is Up Arrow Being Pressed?
	{
		if(keyboard.keys['N'])
		{
			N++;
		}
		else if(keyboard.keys['M'])
		{
			M++;
		}
		else if(keyboard.keys['A'])
		{
			a+=0.05f;
		}
		else if(keyboard.keys['B'])
		{
			b+=0.05f;
		}
		else if(keyboard.keys['C'])
		{
			c+=0.05f;
		}
		else
		{
			xspeed-=0.1f; // If So, Decrease xspeed
		}
	}
	if (keyboard.keys[VK_DOWN]) // Is Down Arrow Being Pressed?
	{
		if(keyboard.keys['N'])
		{
			if(N>2)
				N--;
		}
		else if(keyboard.keys['M'])
		{
			if(M>2)
				M--;
		}
		else if(keyboard.keys['A'])
		{
			if(a>0.05)
				a-=0.05f;
		}
		else if(keyboard.keys['B'])
		{
			if(b>0.05)
				b-=0.05f;
		}
		else if(keyboard.keys['C'])
		{
			if(c>0.05)
				c-=0.05f;
		}
		else
		{
			xspeed+=0.01f; // If So, Decrease xspeed
		}
	}
	if (keyboard.keys[VK_RIGHT]) // Is Right Arrow Being Pressed?
	{
		yspeed+=0.1f; // If So, Increase yspeed
	}
	if (keyboard.keys[VK_LEFT]) // Is Left Arrow Being Pressed?
	{
		yspeed-=0.1f; // If So, Decrease yspeed
	}
	if (keyboard.keys[VK_RETURN]) // Is Left Arrow Being Pressed?
	{
		xspeed=0;
		yspeed=0;
		zspeed=0;
	}
	xrot +=xspeed*loopTime; // Add xspeed To xrot
	yrot +=yspeed*loopTime; // Add yspeed To yrot
	zrot +=zspeed*loopTime; // Add yspeed To yrot

	setUpdated(TRUE);
}

};

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdMap)
{
	return Lio::ellipsoid.main(hInstance,hPrevInstance,lpCmdLine,nCmdMap);
}